﻿using System;
using System.Diagnostics.CodeAnalysis;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using Beeldbankmvc.Models;
using System.Configuration;

namespace Beeldbankmvc.Controllers
{
    [HandleErrorWithELMAH]
    public class AccountController : Controller
    {
        public IFormsAuthenticationService FormsService { get; set; }
        public IMembershipService MembershipService { get; set; }

        protected override void Initialize(RequestContext requestContext)
        {
            if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
            if (MembershipService == null) { MembershipService = new AccountMembershipService(); }

            base.Initialize(requestContext);
        }

        // **************************************
        // URL: /Account/LogOn
        // **************************************        
        public ActionResult LogOn()
        {
            return View();
        }

        [HttpPost]
        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
            Justification = "Needs to take same parameter type as Controller.Redirect()")]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ValidateUser(model.UserName, model.Password))
                {
                    MigrateShoppingCart(model.UserName);

                    FormsService.SignIn(model.UserName, model.RememberMe);

                    if (!String.IsNullOrEmpty(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "De gebruikersnaam of opgegeven wachtwoord is foutief.");
                    MembershipUser currentUser = Membership.GetUser(model.UserName);
                    if (currentUser != null)
                    {
                        if (currentUser.IsLockedOut)
                            Code.Notification.lockedUserAccount(model.UserName);
                    }
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        private void MigrateShoppingCart(string UserName)
        {
            // Associate shopping cart items with logged-in user
            var cart = ShoppingCart.GetCart(this.HttpContext);

            cart.MigrateCart(UserName);
            Session[ShoppingCart.CartSessionKey] = UserName;
        }

        // **************************************
        // URL: /Account/LogOff
        // **************************************
        [Authorize]
        public ActionResult LogOff()
        {
            FormsService.SignOut();

            return RedirectToAction("Index", "Home");
        }

        // **************************************
        // URL: /Account/Register
        // **************************************
        public ActionResult Register()
        {
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View();
        }

        [HttpPost]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                UserRepository userRepository = new UserRepository();
                MembershipCreateStatus createStatus = userRepository.Add(model);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    // Send notification to administrators regarding the creation 
                    //  of this new account
                    Code.Notification.accountCreated(model.UserName,model.Email);
                    
                    //FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
                    return RedirectToAction("AccountCreated", "Account");
                }
                else
                {
                    ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
                }
            }

            // If we got this far, something failed, redisplay form
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View(model);
        }

        // **************************************
        // URL: /Account/ChangePassword
        // **************************************

        [Authorize]
        public ActionResult ChangePassword()
        {
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                {
                    return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    ModelState.AddModelError("", "Het huidige of het nieuw opgegeven wachtwoord is foutief.");
                }
            }

            // If we got this far, something failed, redisplay form
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View(model);
        }

        // **************************************
        // URL: /Account/ChangePasswordSuccess
        // **************************************
        [Authorize]
        public ActionResult ChangePasswordSuccess()
        {
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View();
        }

        // **************************************
        // URL: /Account/EnhancedAccount
        // **************************************        
        public ActionResult EnhancedAccount(object id)
        {
            string userKey = id.ToString();
            if (!String.IsNullOrEmpty(userKey))
            {
                MembershipUser newUser = Membership.GetUser(new Guid(userKey));
                if (newUser != null)
                {                    
                    newUser.IsApproved = true;
                    Membership.UpdateUser(newUser);
                    FormsService.SignIn(newUser.UserName, false);
                    ViewData["CountryList"] = EnhancedAccountModel.countryList();
                    ViewData["HeaderList"] = EnhancedAccountModel.headerList();
                }
            }

            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult EnhancedAccount(FormCollection collection, EnhancedAccountModel model)
        {
            model.Header = collection["ddlHeader"].ToString();
            model.Country = collection["ddlCountry"].ToString();
            model.FactuurLand = collection["ddlFactuurLand"].ToString();
            
            if (ModelState.IsValid)
            {
                MembershipUser currentUser = Membership.GetUser();
                model.UserId = new Guid(currentUser.ProviderUserKey.ToString());                

                UserRepository userRepository = new UserRepository();
                userRepository.EditEnhancedAccountInfo(model);
                userRepository.Save();

                return RedirectToAction("AccountEditSuccessful");
            }
            else
            {
                ViewData["CountryList"] = EnhancedAccountModel.countryList();
                ViewData["HeaderList"] = EnhancedAccountModel.headerList();
            }

            return View(model);
        }
        
        public ActionResult AccountCreated()
        {
            return View();
        }

        // **************************************
        // URL: /Account/EditAccount
        // **************************************
        [Authorize]
        public ActionResult EditAccount()
        {
            // Provide data to populate dropdown lists
            ViewData["CountryList"] = EnhancedAccountModel.countryList();
            ViewData["HeaderList"] = EnhancedAccountModel.headerList();

            // Get user data to show in form
            MembershipUser currentUser = Membership.GetUser();            
            UserRepository userRepository = new UserRepository();
            EditAccountModel model = userRepository.FindOne(new Guid(currentUser.ProviderUserKey.ToString()));

            return View(model);
        }

        [Authorize]
        [HttpPost]
        public ActionResult EditAccount(FormCollection collection, EditAccountModel model)
        {
            model.Header = collection["ddlHeader"].ToString();
            model.Country = collection["ddlCountry"].ToString();
            model.FactuurLand = collection["ddlFactuurLand"].ToString();
            
            if (ModelState.IsValid)
            {
                MembershipUser currentUser = Membership.GetUser();
                model.UserId = new Guid(currentUser.ProviderUserKey.ToString());

                // Check if email address is unique
                string anyExistingUserName = Membership.GetUserNameByEmail(model.Email);
                if ((anyExistingUserName.ToLower() == currentUser.UserName.ToLower()) || (anyExistingUserName == null))
                {
                    UserRepository userRepository = new UserRepository();
                    userRepository.EditEnhancedAccountInfo(model);
                    userRepository.Save();

                    return RedirectToAction("AccountEditSuccessful", "Account");
                }
                else
                {
                    ModelState.AddModelError("Email", "Het opgegeven emailadres is al in gebruik. Geef a.u.b. een ander emailadres op.");

                    ViewData["CountryList"] = EnhancedAccountModel.countryList();
                    ViewData["HeaderList"] = EnhancedAccountModel.headerList();
                }
            }
            else
            {
                ViewData["CountryList"] = EnhancedAccountModel.countryList();
                ViewData["HeaderList"] = EnhancedAccountModel.headerList();
            }

            return View(model);
        }

        [Authorize]
        public ActionResult AccountEditSuccessful()
        {
            // Get user data to show in form
            MembershipUser currentUser = Membership.GetUser();
            UserRepository userRepository = new UserRepository();
            EditAccountModel model = userRepository.FindOne(new Guid(currentUser.ProviderUserKey.ToString()));

            ViewData["CountryList"] = EnhancedAccountModel.countryList();
            ViewData["HeaderList"] = EnhancedAccountModel.headerList();

            return View(model);
        }

        [Authorize]
        [HttpPost]
        public ActionResult AccountEditSuccessful(FormCollection collection, EditAccountModel model)
        {
            model.Header = collection["ddlHeader"].ToString();
            model.Country = collection["ddlCountry"].ToString();
            model.FactuurLand = collection["ddlFactuurLand"].ToString();

            if (ModelState.IsValid)
            {
                MembershipUser currentUser = Membership.GetUser();
                model.UserId = new Guid(currentUser.ProviderUserKey.ToString());

                // Check if email address is unique
                string anyExistingUserName = Membership.GetUserNameByEmail(model.Email);
                if ((anyExistingUserName.ToLower() == currentUser.UserName.ToLower()) || (anyExistingUserName == null))
                {
                    UserRepository userRepository = new UserRepository();
                    userRepository.EditEnhancedAccountInfo(model);
                    userRepository.Save();

                    return RedirectToAction("AccountEditSuccessful", "Account");
                }
                else
                {
                    ModelState.AddModelError("Email", "Het opgegeven emailadres is al in gebruik. Geef a.u.b. een ander emailadres op.");

                    ViewData["CountryList"] = EnhancedAccountModel.countryList();
                    ViewData["HeaderList"] = EnhancedAccountModel.headerList();
                }
            }
            else
            {
                ViewData["CountryList"] = EnhancedAccountModel.countryList();
                ViewData["HeaderList"] = EnhancedAccountModel.headerList();
            }

            return View(model);
        }

        // **************************************
        // URL: /Account/PasswordForgotten
        // **************************************
        public ActionResult PasswordForgotten()
        {
            return View();
        }

        [HttpPost]
        public ActionResult PasswordForgotten(PasswordForgottenModel model)
        {
            if (ModelState.IsValid)
            {
                // Generate new password for this user
                string userName = model.UserName;
                MembershipUser currentUser = Membership.GetUser(userName);
                if (currentUser != null)
                {
                    // Generate new password
                    string generatedPassword = currentUser.ResetPassword();

                    // Send email notification to user with new generated password
                    Code.Notification.passwordReset(currentUser, generatedPassword);
                }
                // TODO If user does not exist another message must be shown.

                // Redirect to another page
                return RedirectToAction("PasswordResetSuccessful", "Account");
            }

            return View(model);
        }

        public ActionResult PasswordResetSuccessful()
        {
            return View();
        }

        // This method is a dummy method, because it's only needed to be able to show 
        //  the menu item accordingly to the role of the logged-in user; therefore it 
        //  doesn't do anything.
        [Authorize(Roles = "Administrator")]
        public ActionResult AccountAdmin()
        {
            return View();
        }

        // **************************************
        // URL: /Account/Index
        // **************************************
        [Authorize(Roles = "Administrator")]
        public ActionResult Index()
        {
            UserRepository userRepository = new UserRepository();

            return View(userRepository.FindAll());
        }

        // **************************************
        // URL: /Account/Details
        // **************************************        
        [Authorize(Roles = "Administrator")]
        public ActionResult Details(object id)
        {
            string userKey = id.ToString();
            if (!String.IsNullOrEmpty(userKey))
            {
                MembershipUser newUser = Membership.GetUser(new Guid(userKey));
                if (newUser != null)
                {
                    // Provide data to populate dropdown lists
                    ViewData["CountryList"] = EnhancedAccountModel.countryList();
                    ViewData["HeaderList"] = EnhancedAccountModel.headerList();

                    // Get user data to show in form
                    UserRepository userRepository = new UserRepository();
                    EditAccountModel model = userRepository.FindOne(new Guid(userKey));
                    
                    return View(model);
                }
            }

            return View();
        }

        // **************************************
        // URL: /Account/EditAdmin
        // **************************************        
        [Authorize(Roles = "Administrator")]
        public ActionResult EditAdmin(object id)
        {
            string userKey = id.ToString();
            if (!String.IsNullOrEmpty(userKey))
            {
                MembershipUser newUser = Membership.GetUser(new Guid(userKey));
                if (newUser != null)
                {
                    // Provide data to populate dropdown lists
                    ViewData["CountryList"] = EnhancedAccountModel.countryList();
                    ViewData["HeaderList"] = EnhancedAccountModel.headerList();

                    // Get user data to show in form
                    UserRepository userRepository = new UserRepository();
                    EditAccountModel model = userRepository.FindOne(new Guid(userKey));

                    return View(model);
                }
            }

            return View();
        }

        // **************************************
        // URL: /Account/EditAdmin
        // **************************************        
        [Authorize(Roles = "Administrator")]
        [HttpPost]
        public ActionResult EditAdmin(object id, FormCollection collection, EditAccountModel model)
        {
            string userKey = id.ToString();
            if (!String.IsNullOrEmpty(userKey))
            {
                MembershipUser newUser = Membership.GetUser(new Guid(userKey));
                if (newUser != null)
                {
                    model.Header = collection["ddlHeader"].ToString();
                    model.Country = collection["ddlCountry"].ToString();
                    model.FactuurLand = collection["ddlFactuurLand"].ToString();

                    // Get user data to show in form
                    UserRepository userRepository = new UserRepository();
                    userRepository.EditEnhancedAccountInfo(model);
                    userRepository.Save();

                    return RedirectToAction("Details", "Account", new { id = id });
                }
            }

            return View();
        }
    }
}